﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MethodWorx.CMS.Requests;
using MethodWorx.CMS.Services;
using MethodWorx.Core.Validation;
using MethodWorx.CMS.Content;
using MethodWorx.CMS.Configuration;
using MethodWorx.CMS.Plugins;

namespace MethodWorx.CMS.TemplateParser.Installer.Components
{
    public class Content : IInstallationWorkflowComponent, IValidationProvider
    {
        public Workflow.StepExecutionResult Execute(Workflow.IWorkflowExecutionContext context, InstallerWorkflowComponentConfiguration configuration)
        {
            using (var uow = context.CmsDataProvider.GetUnitOfWorkFactory().Begin())
            {
                //  get the variables from the workflow context, used to parse out the information
                //  in the template
                var variables = context.GetAllWorkflowValues();
                //  get the content service to create the page
                var contentService = new ContentService(context.CmsDataProvider);
                //  get the schema service to lookup the template
                var schemaService = new SchemaService(context.CmsDataProvider);
                //  get the template name from the step configuration (parsing the names with any workflow variables)
                var templateName = configuration.ConfigurationElement.GetAttributeValue("template", null, true, context.GetAllWorkflowValues());
                var name = configuration.ConfigurationElement.GetAttributeValue("name", null, true, context.GetAllWorkflowValues());
                var parentId = Guid.Parse(configuration.ConfigurationElement.GetAttributeValue("parent", null, true, context.GetAllWorkflowValues()));

                var parent = contentService.GetPageById(parentId);
                var template = schemaService.GetContentTemplateByName(templateName);


                if(string.IsNullOrEmpty(templateName))
                    throw new Exception("Please enter a template name");

                if(string.IsNullOrEmpty(name))
                    throw new Exception("Please enter a page name");


                var output = contentService.CreateContentItem(new CreateContentItemRequest(parent)
                                                                  {
                                                                      ExistingContentTemplate = template,
                                                                      ContentName = name,
                                                                      CreateAllRequired = false
                                                                  }).First();

                Dictionary<string, ICustomPropertyDetails> properties = new Dictionary<string, ICustomPropertyDetails>();
                //
                //  ok, have our content item, so lets now set its properties
                foreach(var element in configuration.ConfigurationElement.Elements)
                {
                    
                    if(element.Name.ToLower() == "property")
                    {
                        //
                        //  ok, lets create the property
                        var propertyName = element.GetAttributeValue("name", null, true);
                        if(!string.IsNullOrEmpty(propertyName ))
                        {
                            //
                            //  ok, find the property in the template
                            var property = template.Properties.Where(p => p.Name.ToLower() == propertyName.ToLower()).FirstOrDefault();
                            if(property == null || property.Custom == null)
                                throw new Exception("Property '" + propertyName + "' not found.");

                            //
                            //  ok, clone it here
                            property.Custom = (ICustomPropertyDetails)property.Custom.Clone();

                            //
                            //  ok, we have the property
                            //  right lets set it up
                            foreach(var childElement in element.Elements)
                            {
                                var dotNetProperty = property.Custom.GetType().GetProperty(childElement.Name);
                                if(dotNetProperty != null)
                                {
                                    //
                                    //  ok, we have our dot net property, so attempt to set it
                                    dotNetProperty.SetValue(property.Custom,
                                                            Convert.ChangeType(childElement.GetInnerXml(context.GetAllWorkflowValues()),
                                                                               dotNetProperty.PropertyType), null);
                                }
                                else
                                    throw new Exception("Property '" + propertyName + "' not found.");
                            }

                            properties.Add(property.Name, property.Custom);
                        }
                        else
                            throw new Exception("Property name is required in workfow configuration");

                    }


                }

                if (properties.Count > 0)
                    contentService.UpdateContentItemProperties(output.Id, properties);

                uow.Commit();

                return Workflow.StepExecutionResult.Ok(output);
            }
            
        }

        public bool Validate(object instance)
        {
            return true;
        }

        public void AddError(string key, string message)
        {
            throw new Exception(message);
        }

        public bool IsValid()
        {
            return true;
        }
    }
}
